/////////////////////////////////////////////////////////////////////////
// 语法分析
// 包括了AST的数据结构和递归下降的语法解析程序

use std::fmt;
use std::cell::RefCell;

pub trait IType {
	fn type_of(&self)->String;
}

//基类，标识AST的一个节点

pub trait IAstNode:IType  {
	//打印对象信息，prefix是前面填充的字符串，通常用于缩进显示
	fn dump(&self, prefix: &String);
}

//第1种方式实现type_of
//第2种方式Box封装
//pub type AstNode = Box<dyn IAstNode>;

//第3种方式使用enum+match
#[allow(dead_code)]
pub enum AstNodes {
	FunctionDecl(FunctionDecl),
    FunctionBody(FunctionBody),
	FunctionCall(FunctionCall)
}

impl fmt::Display for AstNodes{
	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
		match self {
			AstNodes::FunctionDecl(v) =>  write!(f, "FunctionDecl {}", v.name),
			AstNodes::FunctionBody(_v) =>  write!(f, "FunctionBody"),
			AstNodes::FunctionCall(v) =>  write!(f, "FunctionCall {}", v.name),
		}
    }
}


/**
 * 语句节点
 * 其子类包括函数声明和函数调用
 */
pub trait IStatement : IAstNode {
}

//第1种方式实现type_of
//第2种方式Box封装
//pub type Statement = Box<dyn IStatement>;

//第3种方式使用enum+match
pub enum Statements {
    FunctionDecl(FunctionDecl),
    FunctionCall(FunctionCall),
}

impl Clone for Statements{
	fn clone(&self) -> Statements{
		match self {
            Statements::FunctionDecl(v) =>Statements::FunctionDecl(v.clone()),
            Statements::FunctionCall(v) =>Statements::FunctionCall(v.clone()),
        }
	}
}

/**
 * 程序节点，也是AST的根节点
 */
pub struct Prog {
	pub stmts: Vec<Statements> //程序中可以包含多个语句
}

impl IType for Prog {
	fn type_of(&self)->String{
		return String::from("Prog");
	}
}

impl IAstNode for Prog {
	fn dump(&self, prefix: &String) {
		println!("{}",prefix.to_string() + &String::from("Prog"));
		for stmt in &self.stmts {
			match stmt {
				Statements::FunctionDecl(v) => v.dump(&(prefix.to_string() + "\t")),
				Statements::FunctionCall(v) => v.dump(&(prefix.to_string() + "\t")),
			};
		}
	}
}

impl Clone for Prog{
	fn clone(&self) -> Prog{
		Prog::new(self.stmts.clone())
	}
}

impl Prog{
	pub fn new(stmts: Vec<Statements>) -> Prog {
		Prog{
			stmts: stmts
		}
	}
}

/**
 * 函数声明节点
 */
pub struct FunctionDecl  {
	pub name: String,                       //函数名称
	pub body: Option<RefCell<FunctionBody>> //函数体
}

impl IType for FunctionDecl {
	fn type_of(&self)->String{
		return String::from("FunctionDecl");
	}
}

impl IAstNode for FunctionDecl{
	fn dump(&self, prefix:&String) {
		println!("{}",prefix.to_string() + "FunctionDecl " + &self.name);
		if self.body.is_some() {
			self.body.as_ref().unwrap().borrow().dump(&(prefix.to_string() + "\t"));
		}
	}
}

impl Clone for FunctionDecl{
	fn clone(&self) -> FunctionDecl{
		FunctionDecl::new(self.name.clone(), self.body.clone())
	}
}

impl FunctionDecl{
	pub fn new(name:String, body: Option<RefCell<FunctionBody>>) -> FunctionDecl {
		FunctionDecl{
			name: name,
			body: body
		}
	}
}

/**
 * 函数体节点
 */
pub struct FunctionBody  {
	pub stmts: Vec<FunctionCall>
}

impl IType for FunctionBody {
	fn type_of(&self)->String{
		return String::from("FunctionBody");
	}
}

impl IAstNode for FunctionBody{
	fn dump(&self, prefix: &String) {
		println!("{}",prefix.to_string()+ "FunctionBody");
		for stmt in &self.stmts {
			stmt.dump(&(prefix.to_string() + "\t"));
		}
	}
}

impl Clone for FunctionBody{
	fn clone(&self) -> FunctionBody{
		FunctionBody::new(self.stmts.clone())
	}
}

impl FunctionBody{
	pub fn new(stmts: Vec<FunctionCall>) -> FunctionBody {
		FunctionBody{
			stmts: stmts
		}
	}
}

/**
 * 函数调用节点
 */
pub struct FunctionCall  {
	pub name:       String,
	pub parameters: Vec<String>,
	pub definition_index: i32   //指向函数的声明
}

impl Clone for FunctionCall{
	fn clone(&self) -> FunctionCall{
		FunctionCall::new_all(self.name.clone(), self.parameters.clone(), self.definition_index)
	}
}

impl IType for FunctionCall {
	fn type_of(&self)->String{
		return String::from("FunctionCall");
	}
}

impl IAstNode for FunctionCall{
	fn dump(&self, prefix:&String) {
		if self.name.starts_with("nl.") {
			println!("{}",prefix.to_string() + "SysFuncCall " + &self.name + ", resolved");
		} else{
			if self.definition_index>=0 {
				println!("{}",prefix.to_string() + "FunctionCall " + &self.name + ", resolved");
			} else {
				println!("{}",prefix.to_string() + "FunctionCall " + &self.name + ", not resolved");
			}
		}

		for p in &self.parameters {
			println!("{}", prefix.to_string() + "\tParameter: " + p.as_str());
		}
	}
}

impl FunctionCall{
	pub fn new(name:String, parameters:Vec<String>) -> FunctionCall {
		FunctionCall{
			name:       name,
			parameters: parameters,
			definition_index: -1
		}
	}

	pub fn new_all(name:String, parameters:Vec<String>, definition_index: i32) -> FunctionCall {
		FunctionCall{
			name:       name,
			parameters: parameters,
			definition_index: definition_index
		}
	}
}


pub trait IAstVisitor{
	fn visit_prog(&self, prog :&mut Prog) -> Option<AstNodes>;
}

/**
 * 对AST做遍历的Vistor。
 * 这是一个基类，定义了缺省的遍历方式。子类可以覆盖某些方法，修改遍历方式。
 */
pub struct AstVisitor {
}

impl IAstVisitor for AstVisitor{
	fn visit_prog(&self, prog :&mut Prog) -> Option<AstNodes> {
		let mut ret_val: Option<AstNodes> = None;
		let x = (*prog).clone();
		for stmt in x.stmts {
			//根据stmt的类型，进行不同的处理
			ret_val = match stmt {
				Statements::FunctionDecl(v) => self.visit_function_decl(v),
				Statements::FunctionCall(v) => self.visit_function_call(&v),
			};
		}
		return ret_val;
	}
}

impl AstVisitor{
	
	//通过函数声明，访问函数体
	//这里要看子类如何继承
	pub fn visit_function_decl(&self, function_decl: FunctionDecl) -> Option<AstNodes> {
		return self.visit_function_body(function_decl.body)
	}

	//函数体中，依次执行每个函数调用
	pub fn visit_function_body(&self, function_body: Option<RefCell<FunctionBody>>) -> Option<AstNodes> {
		if function_body.is_none() {
			return None;
		}

		//依次执行函数体中的每个函数调用
		let mut retval :Option<AstNodes> = None;
		let x= function_body.unwrap();
		for stmt in &x.borrow().stmts {
			retval = self.visit_function_call(stmt);
		}
		return retval;
	}

	//执行1次函数调用
	//这里要看子类如何继承
	pub fn visit_function_call(&self, _: &FunctionCall) -> Option<AstNodes> {
		return None;
	}
}
